#include "MainWindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QVariant>

#include "CustomerInfoDialog.h"

/// \todo Delete debug
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initCommonUi();

    connect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(processVRPAction(QAction*)));
    connect(mapWindow, SIGNAL(pinDroped(QPointF)), this, SLOT(processMapInput(QPointF)));
    connect(mapWindow, SIGNAL(circlePointClicked(CirclePointMapPtr)), this, SLOT(processMapCirclePoint(CirclePointMapPtr)));
    connect(ui->removeCustomerButton, SIGNAL(clicked()), this, SLOT(removeSelectedCustomers()));
    connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(clearVRPDocument()));
    connect(ui->customersTable, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(editCustomerAtTable(int,int)));
    connect(ui->addVehicleButton, SIGNAL(clicked()), this, SLOT(addVehicle()));

    vrpDocument = new VRPDocument(this);
    vrpDocument->setRoutingParentWidget(this);

    connect(ui->actionOpen, SIGNAL(triggered()), vrpDocument, SLOT(load()));
    connect(ui->actionSave, SIGNAL(triggered()), vrpDocument, SLOT(save()));
    connect(vrpDocument, SIGNAL(loaded()), this, SLOT(showDocument()));

    ui->vehicleTable->setColumnWidth(ColVehicle, 80);
    ui->vehicleTable->setColumnWidth(ColCost, 60);
    ui->vehicleTable->setColumnWidth(ColCap, 60);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initCommonUi()
{
    ui->actionRunOptimization->setIcon(QIcon(":/Resources/images/play.png"));
    ui->actionStopOptimization->setIcon(QIcon(":/Resources/images/stop.png"));
    ui->actionSettings->setIcon(QIcon(":/Resources/images/settings.png"));
    ui->actionSetDepo->setIcon(QIcon(":/Resources/images/depo.png"));
    ui->actionAddCustomer->setIcon(QIcon(":/Resources/images/add.png"));
    ui->actionNavigate->setIcon(QIcon(":/Resources/images/cursor.png"));
    ui->actionClear->setIcon(QIcon(":/Resources/images/clear.png"));
    ui->actionOpen->setIcon(QIcon(":/Resources/images/open.png"));
    ui->actionSave->setIcon(QIcon(":/Resources/images/save.png"));

    mapWindow = new MapWindow(this);
    QMdiSubWindow* subWnd=  ui->mdiArea->addSubWindow(mapWindow);
    subWnd->resize(QSize(700, 500));
    subWnd->move(20, 20);
    subWnd->show();

    actionGroup = new QActionGroup(this);
    actionGroup->addAction(ui->actionSetDepo);
    actionGroup->addAction(ui->actionAddCustomer);
    actionGroup->addAction(ui->actionNavigate);
    ui->actionNavigate->setChecked(true);
}

void MainWindow::processVRPAction(QAction *vrpAction)
{
    if(vrpAction != ui->actionNavigate)
        mapWindow->setUsePin(true);
    else
        mapWindow->setUsePin(false);
}

void MainWindow::processMapInput(const QPointF coordinate)
{
    QAction* currentAction = actionGroup->checkedAction();
    ui->actionNavigate->trigger();
    if(currentAction == ui->actionAddCustomer)
    {
        if(!vrpDocument->getDepo())
            QMessageBox::critical(this, "Error creating new customer.", "Unable create customer without depo.");
        else
        {
            CustomerPtr customer;
            CustomerInfo ci;
            ci.coordinate = coordinate;

            if(inputCustomerInfo(ci))
            {
                customer = vrpDocument->addCustomer(ci);
                if(!customer)
                    QMessageBox::critical(this, "Error creating new customer.", "Unable create customer. Problem with routing.");
                else
                {
                    /// We must add LineString before point
                    mapWindow->addLineString(customer->getDepoRoute(),
                                             vrpDocument->getDepo()->getCoordinate());
                    mapWindow->addCirclePoint(customer->getCoordinate());
                    qDebug()<<"Added customer: "<<ci.toString();

                    addCustomerToTable(customer);
                }
            }
        }
    }
    else if(currentAction == ui->actionSetDepo)
    {
        DepoPtr depo = vrpDocument->getDepo();
        if(depo)
            QMessageBox::critical(this, "Error creating new depo.", "Unable change depo in this version of VRPSolver.");
        else
        {
            vrpDocument->setDepo(coordinate);
            depo = vrpDocument->getDepo();

            CirclePointMapPtr cp = depo->getCoordinate();
            mapWindow->addCirclePoint(cp);
        }
    }
}

void MainWindow::processMapCirclePoint(CirclePointMapPtr point)
{
    CustomerPtr customer = vrpDocument->customerAtPoint(point);
    if(customer)
    {
        CustomerPtrDialog* dlg = new CustomerPtrDialog(customer, this);
        dlg->exec();
    }
}

bool MainWindow::inputCustomerInfo(CustomerInfo &info)
{
    info.isBackhaul = false;
    info.demand = 1;
    info.name = "";

    QString customerName = "Customer #" + QString::number(vrpDocument->getCustomersCount() + 1);
    CustomerInfoDialog* dlg = new CustomerInfoDialog(info, customerName, this);

    int res = dlg->exec();
    dlg->deleteLater();

    if(res == QDialog::Accepted)
        return true;
    else
        return false;
}

void MainWindow::addCustomerToTable(CustomerPtr customer)
{
    /// Add new row to end of table widget
    ui->customersTable->setRowCount(ui->customersTable->rowCount() + 1);

    /// Item for cells
    QTableWidgetItem *item = new QTableWidgetItem();
    item->setCheckState(Qt::Unchecked);

    /// Index of last row
    int rowIndex = ui->customersTable->rowCount() - 1;

    /// Row text color
    QColor rColor = customer->getType()?Qt::green:Qt::blue;

    /// QVariant with cutomer, thanks to qRegidterMetaType()
    QVariant cVar;
    cVar.setValue(customer);

    /// Set delete check box
    item->setTextColor(rColor);
    ui->customersTable->setItem(rowIndex, ColCheck, item);

    /// Set customer name to table
    item = new QTableWidgetItem(customer->getName());
    item->setTextColor(rColor);
    item->setData(Qt::UserRole, cVar);
    ui->customersTable->setItem(rowIndex, ColName, item);

    /// Set customer demand to table
    item = new QTableWidgetItem(QString::number(customer->getDemand()));
    item->setTextColor(rColor);
    ui->customersTable->setItem(rowIndex, ColDemand, item);
}

void MainWindow::removeSelectedCustomers()
{
    CustomerPtr customer;
    QVariant cVar;

    for(int i = 0; i < ui->customersTable->rowCount(); i++)
    {
        if(ui->customersTable->item(i, ColCheck)->checkState() == Qt::Checked)
        {
            cVar = ui->customersTable->item(i, ColName)->data(Qt::UserRole);
            customer = cVar.value<CustomerPtr>();
            removeCustomer(customer);
            ui->customersTable->removeRow(i);
            i--;
        }
    }
}

void MainWindow::removeCustomer(CustomerPtr customer)
{
    mapWindow->removeCirclePoint(customer->getCoordinate());
    mapWindow->removeLineString(customer->getDepoRoute());
    vrpDocument->removeCustomer(customer);
}


void MainWindow::clearVRPDocument()
{
    mapWindow->removeAllGepmetry();
    mapWindow->updateMap();

    ui->customersTable->clearContents();
    ui->customersTable->setRowCount(0);

    ui->vehicleTable->clearContents();
    ui->vehicleTable->setRowCount(0);

    vrpDocument->clear();
}

void MainWindow::editCustomerAtTable(int row, int /*column*/)
{
    QVariant cVar = ui->customersTable->item(row, ColName)->data(Qt::UserRole);
    CustomerPtr customer = cVar.value<CustomerPtr>();
    if(customer)
    {
        CustomerPtrDialog* dlg = new CustomerPtrDialog(customer, this);
        dlg->exec();
    }
}

void MainWindow::showDocument()
{
    mapWindow->removeAllGepmetry();
    mapWindow->updateMap();

    ui->customersTable->clearContents();
    ui->customersTable->setRowCount(0);

    ui->vehicleTable->clearContents();
    ui->vehicleTable->setRowCount(0);

    if(!vrpDocument->isEmpty())
    {
        DepoPtr depo = vrpDocument->getDepo();
        CirclePointMapPtr cp = depo->getCoordinate();
        mapWindow->addCirclePoint(cp);

        CustomerPtr customer;
        foreach(customer, vrpDocument->customerListRef())
        {
            mapWindow->addLineString(customer->getDepoRoute(),
                                     vrpDocument->getDepo()->getCoordinate());
            mapWindow->addCirclePoint(customer->getCoordinate());
            addCustomerToTable(customer);
        }

        VehiclePtr vehicle;
        foreach(vehicle, vrpDocument->vehicleListRef())
            addVehicleToTable(vehicle);
    }

}

void MainWindow::addVehicle()
{
    VehiclePtr vehicle = vrpDocument->addVehicle();
    addVehicleToTable(vehicle);
}

void MainWindow::addVehicleToTable(VehiclePtr vehicle)
{
    /// Add new row to end of table widget
    ui->vehicleTable->setRowCount(ui->vehicleTable->rowCount() + 1);

    /// Item for cells
    QTableWidgetItem *item = new QTableWidgetItem();
    item->setCheckState(Qt::Unchecked);

    /// Index of last row
    int rowIndex = ui->vehicleTable->rowCount() - 1;

    /// Set delete check box
    ui->vehicleTable->setItem(rowIndex, ColDel, item);

    /// Set vehicle name
    item = new QTableWidgetItem(vehicle->name());
    ui->vehicleTable->setItem(rowIndex, ColVehicle, item);

    /// Set vehicle cost
    QSpinBox* costBox = new VehicleSpinBox(vehicle, VehicleSpinBox::CostSpin, ui->vehicleTable);
    ui->vehicleTable->setCellWidget(rowIndex, ColCost, costBox);
    costBox->setValue(vehicle->cost());

    /// Set vehicle capacity
    QSpinBox* capBox = new VehicleSpinBox(vehicle, VehicleSpinBox::CapacitySpin, ui->vehicleTable);
    ui->vehicleTable->setCellWidget(rowIndex, ColCap, capBox);
    capBox->setValue(vehicle->capacity());
}

VehicleSpinBox::VehicleSpinBox(VehiclePtr vehicle, int type, QWidget *parent)
    :vehicle_(vehicle), type_(type)
{
    connect(this, SIGNAL(valueChanged(int)), this, SLOT(changeVehicle(int)));
}

VehicleSpinBox::~VehicleSpinBox()
{
}

void VehicleSpinBox::changeVehicle(int val)
{
    if(type_ == CostSpin)
        vehicle_->setCost(val);
    if(type_ == CapacitySpin)
        vehicle_->setCapacity(val);
}
